/*
 * Copyright (C) 2007-2010 Crise, crise<at>mail.berlios.de
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "stdafx.h"
#include "MPPlugin.h"

HHOOK hHook = NULL;
WNDPROC oldWndProc = NULL;
BOOL bProcessMsg = TRUE;

// Plugin main function
Bool DCAPI pluginMain(PluginState state, DCCorePtr core, dcptr_t pData) {
	switch(state) {
		case ON_INSTALL:
		case ON_LOAD: {
			MPPlugin::newInstance();
			return MPPlugin::getInstance()->onLoad(core, (state == ON_INSTALL));
		}

		case ON_UNINSTALL:
		case ON_UNLOAD: {
			Bool isSafe = MPPlugin::getInstance()->onUnload();
			MPPlugin::deleteInstance();
			bProcessMsg = FALSE;
			return isSafe;
		}

		case ON_CONFIGURE:
			return MPPlugin::getInstance()->onConfig((HWND)pData);
		default:
			return False;
	}
}

LRESULT CALLBACK toolbarProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	LRESULT res = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);

	// Plugin has been uinstalled
	if(!bProcessMsg)
		return res;

	switch(uMsg) {
		case WM_ACTIVATE: {
			MPPlugin::getInstance()->onWindowActivated(hWnd);
		} break;
		case WM_NOTIFY: {
			MPPlugin::getInstance()->onWindowNotify(lParam);
		} break;
	}

	return res;
}

LRESULT CALLBACK CbtHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
	if(nCode < 0 || !bProcessMsg)
		return CallNextHookEx(hHook, nCode, wParam, lParam);

	switch(nCode) {
		case HCBT_CREATEWND: {
			if(oldWndProc == NULL) {
				LPCBT_CREATEWND lpCbtCreate = (LPCBT_CREATEWND)lParam;
				if(lpCbtCreate->lpcs->hwndParent == MPPlugin::getInstance()->getAppWindow()) {
					oldWndProc = (WNDPROC)GetWindowLongPtr(lpCbtCreate->lpcs->hwndParent, GWLP_WNDPROC);
					SetWindowLongPtr(lpCbtCreate->lpcs->hwndParent, GWLP_WNDPROC, (LONG_PTR)toolbarProc);
				}
			}
		} break;
		case HCBT_DESTROYWND: {
			if(oldWndProc != NULL && MPPlugin::getInstance()->getAppWindow() == (HWND)wParam)
				SetWindowLongPtr((HWND)wParam, GWLP_WNDPROC, (LONG_PTR)oldWndProc);
		} break;
	}

	return CallNextHookEx(hHook, nCode, wParam, lParam);
}

BOOL APIENTRY DllMain(HANDLE /*hModule*/, DWORD dwReason, LPVOID /*lpReserved*/) {
	if(dwReason == DLL_PROCESS_ATTACH) {
		hHook = SetWindowsHookEx(WH_CBT, CbtHookProc, GetModuleHandle(NULL), GetCurrentThreadId());
	} else if(dwReason == DLL_PROCESS_DETACH) {
		UnhookWindowsHookEx(hHook);
	}
	return TRUE;
}

extern "C" {

	// Plugin loader
	DCEXP DCMAIN DCAPI pluginInit(MetaDataPtr info) {
		info->name = PLUGIN_NAME;
		info->author = PLUGIN_AUTHOR;
		info->description = PLUGIN_DESC;
		info->web = PLUGIN_WEB;
		info->version = PLUGIN_VERSION;
		info->apiVersion = DCAPI_CORE_VER;
		info->guid = PLUGIN_GUID;

		return &pluginMain;
	}

}